home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-05-05 | 89.4 KB | 2,187 lines | [TEXT/R*ch] |
- Newsgroups: comp.sys.mac.programmer.misc,comp.sys.mac.programmer.info,comp.answers,news.answers
- Subject: The Mac Programming FAQ Answer sheet. [READ ME!]
- Followup-To: comp.sys.mac.programmer.misc
- Approved: news-answers-request@MIT.Edu
- Expires: 23 May 1995 00:00:00 GMT
-
- Archive-name: macintosh/programming-faq
-
- Mac Programming Frequently Asked Questions Answer Sheet
- Last update: 10 May 95 - sharp dressed FAQ
-
- Please download a copy of this answer sheet and search it before you
- post to the 'net, to help reduce bandwidth.
-
- Please send all correspondence regarding content directly to the current
- caretaker and content editor, Chris Thomas, <thunderone@delphi.com>.
- All submissions sent will be considered to be in the public domain
- unless stated otherwise (in which case they will not be included in this
- FAQ sheet). When writing, be sure that you include something
- appropriate in the subject line. I'm now automatically deleting mail
- with blank or whitespace subjects unread due to the growing nasty
- practice of sending junk email without a subject. The idea, apparently,
- is to be cute and get you to read the mail without deleting it. This
- sheet was started and is distributed by Jon Watte, whom you may reach as
- <h+@austin.metrowerks.com>.
-
- This sheet is currently archived on nada.kth.se where you can reach it
- using afs as /afs/nada.kth.se/public/ftp/pub/hacks/mac-faq/CSMP_PD_FAQ
- or using anonymous FTP as pub/hacks/mac-faq/CSMP_PD_FAQ You can also
- find it on rtfm.mit.edu unedr the name macintosh/programming-faq. WWW
- version is available as <http://www.nada.kth.se/~d88-jwa/mac-faq.html>.
-
- No FAQ can substitute for real documentation (some of which is
- mentioned in this FAQ) If you ask a question in comp.sys.mac.programmer
- which has a good answer in one of the important sources, you will probably
- not get an answer. (Inside Macintosh, Macintosh Technical Notes being
- important sources).
-
- There is NO or VERY LIMITED error checking in the code examples, FOR
- BREVITY ONLY. You should make sure you ALWAYS check ALL return codes,
- and handle any that you are not prepared to deal with appropriately.
- Needless to say, do not use the code as is.
-
- Exciting new stuff: More general dev tools update. See especially
- question 1.2. List Manager replacements. The usual tweaking.
-
- Topics:
- [search for *number* to find a topic quickly]
- [topics changed since last FAQ are marked with "+", new topics with ">"]
-
- 1. +Development Tools
- getting started, tool-specific issues
- 2. Memory
- handles, large arrays, resource handles
- 3. User Interfacing
- menus, windows, events, multitasking
- 4. Files
- Mac fopen, wdrefnums, getting full pathnames
- 5. Imaging
- QuickDraw and the means to avoid it
- 6. Text
- Text editing packages, string conversion
- 7. Communications and Networking
- Serial ports, TCP/IP, sockets
- 8. Interapplication Communication
- AppleEvents, OSA, Scripting, and You
- 9. Dynamic Linking & Code Resources
- the dynamics of code resources & trap patches
- 10. Compatibility
- gestalt & glue
- 11. Optional System Software
- 11.1. QuickTime
- codec details and the lack thereof
- 12. Third-Party Solutions
- 12.1. Databases
- client/server solutions for the masses
- 12.2. >Circumventing Toolbox Limitations
- foul baggage begone- List Manager replacements
- 13. Dessert
- yummies the Macintosh Way
- 14. Contributors
- whodunnit
-
- *1* Development and debugging tools for the Macintosh
-
- 1.1) Q: What do I need to start writing Macintosh software?
-
- A: A Mac, a lot of time, and a few hundred $. Although you can develop
- software on a Classic-type machine, it is not to be attempted by the
- weak of heart or stressed of time. If you're doing paid work and/or
- work for a company, a Quadra-class machine is a must; remember that your
- time costs your employer much more than just your salary. A PowerMac is
- highly preferable. 16 MB is a minimum to run at all comfortably (40 MB
- recommended), and Virtual Memory (including RamDoubler, unfortunately)
- is not suited for development work. Similarly, if you don't have at
- least 80 MB free on your hard disk you need to buy more space. You will
- also need a CD-ROM drive.
-
- You need a development system such as CodeWarrior, MPW Pro, Symantec C++
- 8.0 or Prograph, you need at least some of the New Inside Mac books
- (Toolbox Essentials, Files, Memory come to mind) and a good entry-level
- third-party book may help.
-
- Once you are up to speed on the general layout of the Mac and its
- toolboxes, you should call APDA and order the monthly developer mailing,
- which will give you a CD chock full of documentation, utilities and
- system software once a month. You will also, obviously, need a CD
- player; Apple's own CD600 is a very good buy at the time of this
- writing. If you don't have the dough for the monthly mailing
- ($250/year) you can order a _develop_ subscription; this quarterly
- magazine ($30-$50/year) comes with a CD containing most Inside Mac
- documentation. Another good product to order is the MacOS SDK, which
- for $99 gives you a CD with every API in existence up to and including
- the 7.5 Mac Toolbox additions. It's somewhat redundant if you already
- have the Developer CD subscription. <apda@appplelink.apple.com> Apple's
- Developer Web has almost all of the contents of the Developer CD online.
- <http://www.info.apple.com/dev>
-
- If you don't know how to program, go learn your language of choice
- BEFORE attempting a "real" Mac application. Programming is a discipline
- often requiring different thought processes than your normal day job. A
- beginning book, like Lippman: The C++ Primer, one of the Teach Yourself
- C++ books, or the primers available on the CodeWarrior CD, might help.
-
- An indispensable Mac programming tool is the Macintosh Programmer's
- Toolbox Reference (MPTA), an up-to-date hypertext reference guide
- containing reference material on the New Inside Mac-documented portions
- of the Toolbox with lightning-fast look-up and mostly correct usage
- hints and code snippets. MPTA can be found on the Developer CD, and is
- also offered on a seperate $99 CD. <apda@applelink.apple.com>
-
- Think Reference version 2.0.1, precursor to MPTA, contains reference
- material on many parts of the Mac toolbox with lightning-fast look-up
- and mostly correct usage hints and code snippets. While it does not
- cover any post-System 7 system additions, nor the modern "universal"
- headers format, it does include information on the standard C/C++
- libraries. Available wherever fine Symantec products are sold -
- <apda@applelink.apple.com> for one.
-
- 1.2) Q: What is the most used Macintosh development system?
-
- A: Currently, the three most widely used are CodeWarrior (CW), MPW, and
- Symantec C++, probably in that order, though I don't have any
- statistics. The latest version of any one of these is adequate for Mac
- development.
-
- CodeWarrior: In early 1994, CodeWarrior came out of nowhere and grabbed
- a large share of the market visibility because they had the fastest
- compiler and they generated PowerPC code as well as 68K code. Today,
- CodeWarrior has the smoothest development environment and most complete
- C++ implementation, supporting both templates and exceptions. CW/6
- includes C, C++, and Object Pascal support, and can generate x86
- binaries. Among hobbyists, CW seems to be the most popular because of
- it's low price, ultra-fast compile time, and support that no other
- company on the planet can match. See comp.sys.mac.programmer.codewarrior
- for more information and CodeWarrior-related praise. Contact
- <sales@metrowerks.com>.
-
- MPW: The grandaddy of all Mac development environments, descended from
- the original Mac development environment based on a Lisa. MPW is an
- extremely flexible, powerful, Unix-like command line environment with
- makefile, multiple windows and split-pane support. Many development
- tools are MPW-based. MPW Pro comes with C, C++, Pascal, assemblers for
- both 68k and PowerMac, various other useful tools, and the C++-based
- framework MacApp for a reasonable price. MPW has in the past been
- extremely slow, but shows signs of redemption. Contact
- <apda@applelink.apple.com>.
-
- Symantec C++: This is the eighth-generation descendant of the C
- environment favored by Mac developers for over five years. Symantec C++
- 8.0 is a complete, scriptable, modular development environment including
- C, C++, and soon, a PowerPC assembler. The C++ implementation supports
- templates. A development version of a PowerPC C++ compiler supporting
- exceptions and RTTI is available at Symantec's devtools site. SC++ 8.0
- doesn't at this time support 68k Mac development. For that purpose,
- you're required to use the old, decrepit TPM development environment,
- which is included. Contact <sales@devtools.symantec.com>.
-
- There are also at least two Fortran compilers, at least three SmallTalk
- implementations (ObjectWorks, SmallTalk/V and SmallTalkAgents) and
- others. There are ways of stripping SmallTalk apps so they're smaller
- and faster as standalone apps than in the environment.
-
- Languge Systems has Object Pascal and Fortran for PowerMac. Absoft has
- Fortran and C++ for PowerMac. These all require MPW.
-
- There's also a world-class LISP/CLOS implementation from Apple called
- Macintosh Common Lisp. Recently, Apple announced that DigiTool has
- licensed MCL with the intent (among other things) to provide a PowerMac
- version and other updates.
-
- Zedcor has FutureBasic, which seems to be a very popular... It also
- seems to be the only well-supported implementation of BASIC on
- Macintosh.
-
- CSI has MacForth, of which I only know the name and someone who says
- it's pretty good.
-
- There is another good Common Lisp implementation: Procyon Common Lisp.
- I don't know if it is actively supported, but Procyon CL is also
- available for DOS, OS/2 and Windows (as Allegro CL/PC) and actively
- developed.
-
- A new possible up-and-coming languge is Apple's Dylan, which is
- something of a cross between BASIC, Pascal, and C. C-based code can be
- used directly from Dylan, but Dylan can't yet be used directly from C.
- The Apple Dylan environment is rumored to be as far beyond MPW as MPW is
- beyond thick bundles of FORTRAN punch cards.
-
- 1.3) Q: Okay, which is the most used Mac programming languge?
-
- A: The existing Macintosh code base is mostly C, with C++ second, and
- Pascal finding it's niche in third. Few people are writing mainstream
- software in Pascal anymore, probably because (a) it's rather hard to
- move to non-Mac platforms (b) Pascal is only rarely being taught past
- the first year in Computer Science.
-
- 1.4) Q: Where do I find a free/share/copyleftware C compiler for the Mac?
- Is there a GCC for the mac? What about the FSF boycott of Apple products?
-
- A: There is no really good solution for a "for-free" C development
- system for the Mac. GCC has been ported, but requires the MPW shell and
- MPW assembler to run; these have to be bought from APDA. There is a
- standalone port of GCC 1.37 on nic.switch.ch:software/mac/src/think_c.
-
- gcc-1.37r14 V1.1 standalone is available for ftp at nic.switch.ch:
- software/mac/src/think_c.
-
- A not-entirely-stable port of GCC 2.3.3 to MPW is available for ftp at
- atg.apple.com [anyone know the directory?]. A much more solid port of
- GCC 1.37 is available for MPW as well.
-
- Stan Shebs <shebs@cygnus.com>, the driving force behind all of the MPW
- GCC ports, is working on a new port of GCC 2.5.8.
-
- For those whose main interest is in developing only text-based C/C++
- programs, using GCC under MacMiNT might be appropriate. MacMiNT is a
- UNIX like operating system ported from the Atari ST which supports many
- freely available UNIX utilities like GCC, GDB, make, tcsh, byacc, perl,
- and more. MacMiNT stuff can be found at nic.switch.ch in
- 'software/mac/src/macmint'.
-
- The FSF/LPF boycott of Apple products is over as of January 1995, which
- means they will now incorporate changes made for Macintosh into their
- main code base, if such changes are easily incorporated, and they
- won't be any more antagonistic to Mac programmers than they would be
- to any other micro-to-workstation-class programmers.
-
- So what are you waiting for? Go out and port something from GNU! Send in
- the changes! We still lack decent free development tools!
-
- 1.5) Q: Are there any other free Mac development platforms?
-
- A: The best source for information on free compilers/interpreters is the
- Free Compilers FAQ which is written by Brian Connors
- <connorbd@cleo.bc.edu>. Watch for it in c.s.m.p.info.
-
- 1.6) Q: What's the difference between the MPW, Think and CodeWarrior
- environments?
-
- A: As of CodeWarrior/6, MPW 3.3, and Symantec C++ 8.0.1 (SC++),
- CodeWarrior will allow faster turnaround times, MPW will provide the
- most flexibility and overall power, and Symantec C++ has the edge with
- regard to helpful project browsing features.
-
- CW C++ supports templates and exceptions, Symantec C++ supports only
- templates, MPW's new compilers are based on Symantec C++.
-
- SC++ 8 doesn't generate 68k code, while pre-CW/6 CodeWarrior requires
- you to use seperate (virtually identical) environments, and builds are
- controlled from a Makefile in MPW, of course.
-
- All three need much hard disk space. SC++ requires the most RAM. MPW
- requires the most disk space.
-
- MPW is the slowest, followed distantly by SC++, which is followed
- closely by CodeWarrior.
-
- The best thing about MPW is that you can write scripts and make files to
- do anything you want in the way you want it. SC++ and CodeWarrior can
- be AppleScripted to do builds that require more than one link operation,
- but the process is more involved, and CW doesn't currently support
- scripting in full. SC++ 8 can do builds which require more than one
- link operation.
-
- For the MPW and CodeWarrior environments, there are four source level
- debuggers; Metrowerks, SADE, SourceBug, Voodoo Monkey. The latter is an
- experimental debugger with support for threads debugging; the middle is
- bundled with MPW while SADE has to be bought separately (but is fully
- scriptable in its own scripting language). Metrowerks Debugger is
- included with CodeWarrior.
-
- The Think environments have their own integrated debuggers; the Think
- Pascal one has a lot of useful features while the Think C/C++ one is a
- little more basic (but is gaining in functionality with each release).
-
- Metrowerks has their own debugger which works like the MPW debuggers; i e
- it runs the application standalone and pokes at it from the outside,
- while the Think debuggers run the application "wrapped" in a special
- environment, making for some subtle interferences with your heap (which
- you usually don't notice). The Metrowerks Debugger is Thread
- Manager-savvy on the 68k side.
-
- BOTTOM LINE:
-
- If you're developing for both Power and regular 68k Macs, you need
- CodeWarrior. MPW is an option which makes sense if you need to develop
- code for non-CFM OpenTransport or if you have a ridiculously large
- number of independent code modules to compile, or if you're a Unix
- person. CodeWarrior, in addition to it's own integrated environment,
- includes the non-compiler parts of MPW and MPW-hosted Metrowerks
- compilers/linkers. SC++ is an option only for PowerMac development.
-
- 1.7) Q: What is a good low-level debugger for the Mac?
-
- A: MacsBug is freely available for ftp from <ftp://ftp.apple.com>; log
- in as user anonymous and give your FULL e-mail address as password.
- MacsBug is your basic monitor-type debugger that takes a few hundred Ks
- of memory, and lets you break, step, disassemble, look at the stack etc
- of most anything running on your Mac. Since it's free (it's also on the
- developer CDs) and provides most of the functionality you need, this is
- a popular choice. As of 6.5d10, Macsbug supports PowerPC debugging.
-
- Jasik Designs has a debugger called The Debugger which can do both low-
- and high-level debugging, with or without source and for all types of
- code, application, code resources, everything. This is the debugger of
- choice for many large developers because of its high power and many
- features not found anywhere else. However; newcomers beware! This is
- the Lamborghini of debuggers; if you know how to drive it, it is the
- fastest way from A to B; if you don't, you'll just end up in the ditch.
- The Debugger is PowerMac native and supports PowerPC disassembly. It
- includes an excellent code coverage tool and MacNosy, a general
- disassembler. Support is direct from the author and generally great.
- <macnosy@jasik.com>
-
- 1.8) Q: Are there any visual developments environments for the
- Mac (comparable to Visual C++)?
-
- A: There is no Visual C++ as such. However, there is a C++ parser/editor
- called ObjectMaster which provides good browsing and editing capabilities
- if you already have a C++ compiler. A demo is available on the CodeWarrior
- CD. Think C++ comes with a browser built-in, and you can edit
- dialogs/windows using plain old ResEdit, even for your custom view types.
-
- Symantec C++ 7.0 also bundles a view editor/code generator called Visual
- Architect; it is fairly complete and has a good level of integration
- into the Think Project Manager.
-
- AppMaker is a GUI builder/code generator. Granted, it's not as nice as
- VC++, but it's quite a product in any case.
-
- MarksMan version 3.0 has totally revised TCL templates, and now
- generates well-thought-out TCL code. It can also generate ANSI C code
- etc.
-
- Also, Neuron Data has their UI tool called Open Interface, which is
- better than VC++ and creates code portable across 35 platforms.
- Unfortunately it's $2500 per developer per platform. There's also two
- other cross-platform products called XVT and Galaxy, the former has
- gotten flak on UseNet while the latter reportedly is the premier
- cross-platform application builder framework; with everything from
- styled text to network support.
-
- There is a fully visual, dynamic, object oriented data-flow-driven
- programming language for the Mac called Prograph CPX. It features a
- full-featured class library, a powerful, user-extensible GUI Builder, full
- access to the entire Mac toolbox, a database engine, high-level interfaces
- to SQL, Oracle, etc. But the coolest thing about Prograph is its
- interpretative debugger, fully integrated with the visual code editor,
- which lets you write your code _while it's running_. Execution
- automatically rolls back to where changes you make have relevance. A
- PowerMac-native compiler and a Windows version are expected in '95. A
- complete demo version is available from <sales@prograph.com>. Cost is
- $695 ($395 for students).
-
- SmalltalkAgents comes with a GUI builder, which lets you draw your
- interface, and then outputs the code for you.
-
- If you'd rather do Common Lisp, Macintosh Common Lisp offers a Common
- Lisp Object System with support for most Mac interface items; you can
- edit code while it is running and build stand-alone applications.
-
- However, all of these tools generate rather larger binaries with larger
- system demands than a program written in C. On the other hand; C++
- programs require more memory and disk space than programs written in
- assembly. It's a trade-off, and I believe this type of tools is the
- wave of the near future.
-
- 1.9) Q: What class libraries are there for the Mac?
-
- A: Apart from the libraries mentioned above, there are three contenders:
- MacApp, TCL, and PowerPlant. "Bedrock" will never be released as a
- product, although parts of it surface in TCL 2.0 and other parts will be
- the base for the OpenDoc Parts Framework.
-
- MacApp is a heavy-duty class library that has tons of features and a
- steep learning curve; it runs under MPW with Pascal or C++, and also
- under Think Pascal 4.0 A major application written in MacApp is
- PhotoShop.
-
- TCL stands for Think Class Library and comes with Think Pascal, C or
- C++. It is a smaller library that still fills most peoples needs; since
- Think C implements a subset of C++ (the most important OO concepts such
- as virtual functions and inheritance) and the TCL is carefully written
- not to take advantage of any C++ features not in Think C, you can use it
- with Think C. A major application written in TCL is Lotus 1-2-3. (TCL
- 1.1.3) Starting with Symantec C++ 7.0, Think Class Library 2.0 using
- templates and "real" C++ objects is shipping.
-
- The C++ Standard Template Library (STL) compiles under Symantec C++
- and CodeWarrior, and versions are available for both.
-
- PowerPlant is the Metrowerks CodeWarrior offering; it's written by the
- guy who designed the Think Class Library, but it has a lot of
- differences from the original TCL; for one, it's not a monolithic one
- base class framework. On the other hand, it has some catching up to do
- before it reaches the level of MacApp. It is gaining quite fast on TCL,
- but isn't all there yet. It has the most complete support for
- AppleEvents & scripting & drag & drop other modern features.
-
- 1.10) Q: How should I debug and test my software?
-
- A: Get ahold of, and install, the extensions DoubleTrouble,
- DisposeResource and EvenBetterBusError. They will catch 80% of any
- memory related bugs you may have, including many bugs that follow NULL
- handles or pointers. (Jasik's Debugger (see above) obviates the need
- for these.)
-
- A low-level debugger is required, and while you install it, install the
- "leaks" dcmd which will help you catch memory leaks in your application.
- All of these tools are available from <ftp.apple.com>.
-
- 1.11) Q: Are there any good Mac programming magazines?
-
- A: One Mac programming magazine I know of is MacTech Magazine (formerly
- MacTutor). It covers a variety of Mac programming topics on various
- levels. Operating independently from Apple, it has a lot of stuff for
- the beginning Mac programmer, as well as occasional nuggets for the more
- experienced of us. <custservice@xplain.com>
-
- Another VERY GOOD Magazine is _develop_ which is put out by Apple four
- times a year; it comes with a CD containing code for all articles ever
- published in _develop_, and a lot of documentation and system software
- freebies as well. $30/year in the US. <dev.subs@applelink.apple.com>
-
- 1.12) Q: What about protected memory? I'm sick and tired of re-booting
- when my application crashes.
-
- A: Write better software!
-
- Or install The Debugger from Jasik Designs, which can provide your
- application with write-protection of critical parts of memory, if you have
- a 68030-equipped Mac.
-
- Making the Mac OS memory-protected is tricky, because applications expect
- to be able to write to low memory, the system heap, temporary memory,
- window lists, and even each other's heaps in some interapplication
- communication solutions that date back to before AppleEvents and the PPC
- Toolbox. To add to the burden, Apple's own software tends to be the
- worst offender in these cases.
-
- But fear not, Mac fans! Jonathan Kimmitt has written Patmos, the
- "Protected address translation mode operating system". It is an
- application that brings the advantages of protected mode programs to
- your Quadra class Macintosh by the simple expedient of taking over the
- memory management unit of the 68040 in a very simple kernel (<100K in
- size), we immediately gain compatibility with the BSD unix program
- environment. The advantages of this are as follows:
-
- (a) You can run certain programs (such as /bin/sh) designed for MacBSD
- (b) You can compile almost all GNU software including C and C++ without.
- modifying the source code in any way
- (c) All programs run with a flat 32-meg address space, with no worries
- about 32K segments or the other mac paraphernalia.
- (d) The majority of program bugs can be caught cleanly without crashing
- your mac
- (e) All your files are shared between Patmos and MacOS so you can edit
- using your favourite mac editor, then immediately compile in Patmos
- without having to reboot or copy files around.
-
- The downside is that not all macs use the memory management unit in the
- same way, or even have the same kind of MMU, so Patmos may not run on
- your particular mac model. However, since the kernel source code is
- very small, the task of adapting it to a new environment is very simple,
- and once achieved, all application programs running in user mode are
- enabled to run without even recompiling.
-
- <ftp://nic.switch.ch in /software/mac/src/patmos>
-
- 1.13) Q: I have this library written in (Think) Pascal that I want to use
- from Think C/Symantec C, but I get link errors/don't know how to do it.
- What should I do?
-
- A: Start by writing a .h file describing the interface. Remember to
- declare the Pascal functions "pascal". Build a library with Think Pascal
- and convert it with oConv.
-
- Do you get link errors on symbols defined in your Pascal lib? Check the
- capitalisation used.
-
- Do you get errors on symbols like LMUL and LDIV? Those functions are
- defined in the Think Pascal library Runtime.lib or uRuntime.lib. Include
- uRuntime.lib and try again.
-
- Do you get link errors on standard symbols like thePort? This is due to
- bad capitalization in Symantec's libs. Run oConv with .v checked. This
- will create a TEXT file with a .v extension. Open that with a text
- editor and correct the capitalization. Run oConv again, with .v checked
- this time too.
-
- Do you still get errors on standard symbols? Are you using Think
- C/Symantec C++ version 6 or higher? Then you must open the library (after
- converting it) from Think C version 5, and remove the unit named
- %_TOOLBOX. (If I'm not mistaken, this is the toolbox init unit, which
- you won't need anyway.)
-
- 1.14) Q: CodeWarrior vs. Think/Symantec C++: Which is better?
-
- A: See the above discussion on CodeWarrior, Think, and MPW for a full
- understanding of the issues involved.
-
- 1.15) Q: Can CodeWarrior read Think libraries?
-
- A: Yes, in a way. Here are the steps required.
-
- 1) Secure a copy of Think Pascal and a machine that can run it
- 2) Import the Think C library into Think Pascal
- 3) Build a Think Pascal library (in MPW format)
- 4) Import MPW format library into CodeWarrior
-
- 1.16) Q: What are some good books on the subject of learning the Mac
- Toolbox?
-
- A: Any of Dan Parks Sydow's numerous books on the subject. Recommended
- also is Dave Mark's _Ultimate Mac Programming_ (a Macworld book, for
- some odd reason). Stay away from Dave Mark's _Learn C on the Mac_ and
- _Learn C++ on the Mac_.
-
- See also Nick DeMello's books review, posted in c.s.m.p.info from time
- to time.
-
- 1.17) Q: Source code! I want source code! Where can I find some?
-
- A: Celestin Company, Inc. sells the Apprentice 2 CD-ROM. Apprentice
- contains over 600 megabytes of programmer utilities and up-to-date
- source code in CodeWarrior, Symantec, and MPW projects for C, C++, and
- Pascal. <ftp://ftp.teleport.com/vendors/cci/apprentice/apprentice.hqx>
- for an index and info. <celestin@olympus.net>
-
- Also, the alt.sources.mac archive at <ftp://ftpbio.bgsu.edu> contains a
- lot of misc. source code and snippets not found elsewhere.
-
- <ftp://nic.switch.ch> is another good source for unique source code.
-
- Info-mac is a good source for source, info-mac/dev/src.
-
- 1.18) Q: I'm trying to use a largish array in Think C, but get a "code
- overflow" error. This is valid C, why doesn't it work?
-
- A: The ANSI standard does not guarantee that any structure larger than
- 32767 bytes be correctly handled. Because of historical constraints,
- the Mac memory model is built around several small blocks of size 32K or
- less; these are used both for code and global/static data. If you want
- to use more code or data, you have to turn on "far code" or "far data" -
- you still will not get around the restriction of 32K code or data per
- compiled file, though.
-
- This is one area where CodeWarrior's 68k support shines; it works around
- most such limitations and it doesn't cost much in performance either!
-
- As opposed to, say, DOS or Windows, however, you can allocate as much
- memory as you want (and there is in the machine) and step through it
- using ordinary pointers; it's just that global and static data space is
- addressed off the A5 register using a 16bit displacement addressing mode
- in the 68000 processor.
-
- On the PowerPC, everything is 32bit from the start; that runtime model
- is much more like UNIX. The horizon is the limit.
-
- *2* Memory
-
- 2.1) Q: What is a handle?
-
- A: A handle is a pointer to a pointer to something. However, it is more
- than that; creating a handle by taking the address of one of your own
- pointers does NOT create a Handle; the Memory Manager will only deal
- properly with Handles that are created using NewHandle or something that
- calls it (such as NewRgn or GetResource).
-
- 2.2) Q: When do I have to lock a Handle?
-
- A: The contents of a Handle may move, and when it does, the pointer your
- handle is pointing to is changed to point to the new address so your
- handle is always valid. The toolbox may call the memory manager to
- allocate more memory pretty much anytime you call it (the toolbox) and
- when memory is allocated, your handle may move in memory. Don't
- dereference a handle into a pointer (or take the address of a field in a
- record a handle is double-pointing to) and then call the toolbox and
- expect the pointer to still be valid. The only way to ensure that the
- pointer will still be valid is to call HLock on the handle to lock it.
-
- Use HGetState and HSetState to save & restore the "locked" state of a
- handle when you lock it.
-
- 2.3) Q: How do I dispose of Handles?
-
- A: DisposeHandle (formerly called DisposHandle) once and ONLY once will
- do the trick. Trying to dispose of an already disposed Handle is an
- error. DoubleTrouble (see above) will catch such bugs when they do
- occur.
-
- 2.4) Q: What about resources?
-
- A: Calling GetResource returns NULL if the resource is not found or
- there is not enough memory, else it returns a handle to the resource.
- This handle may be moved or locked like any other handle, but DO NOT
- call DisposeHandle to get rid of a resource handle - call
- ReleaseResource. DisposeResource (see above) will catch this kind of
- bug.
-
- Remember that AddResource makes a resource handle out of an ordinary
- handle, and RemoveResource or DetachResource makes an ordinary handle
- out of a resource handle. You cannot call AddResource with a resource
- handle; you have to DetachResource it first.
-
- Resource handles are automagically disposed when the resource file they
- belong to is closed.
-
- *3* User / Machine interaction
-
- 3.1) Q: How do I read the modifier keys of the keyboard?
-
- A: Just call EventAvail and check the event.modifiers field.
- Only works when you are in the foreground. You can also use
- GetKeys(), or (as a last resort) check the lo-mem global KeyMap
- directly.
-
- 3.2) Q: How do I move the mouse cursor to a specific position?
-
- A: Wait! Don't do it! There has to be a better way!
-
- If you feel you HAVE to do it (for a game or VERY special simulation
- situation) you can use the Cursor Device Manager documented in the tech
- notes on <ftp.apple.com>. If that manager is not installed, as it's not
- on older Macs, you can use the following code:
-
- You need to have some low-memory globals defined. they may be defined
- in SysEqu.h.
-
- #define MTemp 0x828
- #define RawMouse 0x82c
- #define CrsrNewCouple 0x8ce
-
- Note that CrsrNewCouple is actually a combination of two globals, just
- to make our life slightly easier.
-
- The code I use to move the mouse is:
-
- *code*
- void
- MoveMouseTo ( Point where ) {
-
- HideCursor ( ) ;
- * ( Point * ) RawMouse = where ;
- * ( Point * ) MTemp = where ;
- * ( short * ) CrsrNewCouple = -1 ;
- ShowCursor ( ) ;
- }
- *end*
-
- You need to hit a couple more global variables if you want this to work
- properly in a multiple-monitor system, but i forget what they are
- offhand. poke through SysEqu.h, and you should be able to figure it out
- without a problem.
-
- On the PowerPC, these lo-mem globals may not be available for native
- applications; however, all Power Macintoshes implement the Cursor Device
- Manager. All Macs made after March '93 (including Centris 650 and 610)
- implement the Cursor Device Manager, in fact.
-
- There is also a file on nada.kth.se:pub/hacks/mac-faq/MoveMouse.c which
- shows how to use the Cursor Device Manager, written by an excellent
- Apple engineer. Grab!
-
- Careful, version 1.0 of the Universal Header "CursorDevices.h" file was
- completely incorrect. Use 2.0a3 or later.
-
- 3.3) Q: My menus don't show up in the menu bar
-
- A: If your menus are hiearchical, you'll have to install them manually;
- GetNewMBar won't do it for you. See also 3.5.
-
- 3.4) Q: When the user selects my menus, I get strange results back; they
- seem to have different menu IDs than my menus?
-
- A: The Menu ID as used by the menu manager is NOT the same thing as the
- MENU resource ID (used in the MBAR resource and with GetMenu()) When you
- create a MENU, ResEdit sets the menu ID to the MENU resource ID, but if
- you re-number the resource, you will have to open the menu in ResEdit
- and change the menu ID using the "Edit MENU ID" menu item.
-
- 3.5) Q: I use GetMenu() to find a menu in the menu bar, and then change
- it, but it seems I have a memory leak OR my changes don't "punch
- through"
-
- A: GetMenu() is only intended if you don't already have the menu "in
- memory." The call you should use almost all the time is GetMHandle()
- which gets the handle to a menu in the current menu bar by its menu ID
- (not resource id).
-
- 3.6) Q: What about pre-emptive multitasking?
-
- A: To the user, the Mac multitasking method, which builds upon each
- application calling WaitNextEvent, GetNextEvent or EventAvail every so
- often and the Process Manager/MultiFinder switching applications only at
- such calls, is at least as good as preemtive multitasking, because the
- present system priotitizes user interface responsiveness over everything
- else. The only shortfall about this is formatting floppies, which locks
- up the Mac CPU. This is because the Mac floppy controller is really
- stupid, and would happen even if the Mac multitasked preemptively.
-
- There IS "real" pre-emptive multitasking available for use in Mac
- applications; the expensive way is buying A/UX 3.0 which can have Mac
- applications written as UNIX processes; the cheap way is installing the
- Thread Manager which will allow you to create pre-emptive threads.
- However, the restrictions on those threads are the same as those on Time
- Manager tasks: don't call any function in an unloaded segment, and don't
- call QuickDraw or any toolbox call which may move memory (which are most
- ToolBox calls; paradoxally, BlockMove is safe :-) as are, surprisingly,
- FSRead and FSWrite). The latest word from Apple is that this
- preemptive support is going away, to be replaced by something else in
- Copland.
-
- There are several problems with making the Mac OS preemptive; including
- apps that draw outside their windows or directly to screen, user
- dragging and other issues. The system is being reimplemented for 8.0
- (Copland) to solve these problems.
-
- *4* Files
-
- 4.1) Q: How do I tell fopen() to open a file the user has selected using
- StandardGetFile?
-
- A: The "standard" ANSI C file functions are less than well suited for
- the Macintosh way of doing things. However, if you are doing a port for
- your own enjoyment and benefit (or maybe for in-house work) you can use
- the following function: (see below about converting a wdRefNum into a
- vRefNum/parID pair)
-
- *code*
- FILE *
- fopen_mac ( short vRefNum , long parID , char * fileName , char * mode ) {
-
- short oldVol ;
- short aVol ;
- long aDir , aProc ;
- FILE * ret = NULL ;
-
- if ( GetVol ( NULL , & oldVol ) ) {
- return NULL ;
- }
- if ( GetWDInfo ( oldVol , & aVol , & aDir , & aProc ) ) {
- return NULL ;
- }
- if ( HSetVol ( NULL , vRefNum , parID ) ) {
- return NULL ;
- }
- ret = fopen ( fileName , mode ) ;
- if ( HSetVol ( NULL, aVol , aDir ) ) {
- /* an error we can't currently handle */
- }
- if ( SetVol ( NULL, oldVol ) ) {
- /* an error we can't currently handle */
- }
- return ret ;
- }
- *end*
-
- All of the above is necessary for one reason or another - if you are
- interested, by all means look HSetVol up in Think Reference 2.0 or New
- Inside Mac: Files.
-
- In older versions of MPW; this wouldn't work since the MPW libraries
- used to do a GetVol and explicitly use that value by itself.
-
- 4.2) Q: When can I use the HOpen, HCreate etc file calls? Are they only
- System 7 calls?
-
- A: All the HXxx calls that take a vRefNum and parID as well as the file
- name are implemented in glue that works on any system that has HFS
- (meaning 3.2 and up with the HD20 INIT, and all systems from System 6
- and up)
-
- The glue is available in MPW 3.2 and up, and Think C 5.0 and up. This
- goes for all HXxx calls except HOpenDF; therefore, if you are interested
- in System 6 compatibility, use HOpen instead and make sure you don't
- allow file names beginning with a period.
-
- 4.3) Q: Why do you say wdRefNum sometimes and vRefNum sometimes?
- Why do you say parID sometimes and dirID sometimes?
-
- A: When the Mac first made an appearance in 1984, it identified files by
- using a vRefNum (volume reference number meaning a floppy disk or later
- hard disk) and a name. Once HFS saw the light of day, folders within
- folders became a reality, and you needed a dirID as well to point out
- what folder you really meant on the volume. However, older programs
- that weren't being rewritten still knew nothing about directory IDs, so
- Apple had SFGetFile make up "fake" vRefNums that didn't just specify a
- volume, but also a parent folder. These are called wdRefNums (for
- working directory) and were a necessary evil invented in 1985. You
- should not create (or, indeed, use) wdRefNums yourself.
-
- There is a system-wide table that maps wdRefNums onto vRefNum/parID
- pairs. There is a limit to the size of this table. A dirID and a parID
- is almost the same thing; you say "parID" when you mean the folder
- something is in, while you say a "dirID" when you mean the folder
- itself. If you for instance have a folder called "Foo" with a folder
- called "Bar" in it, the parID for "Bar" would be the dirID for "Foo."
-
- 4.4) Q: How do I convert a wdRefNum as returned by SFGetFile
- into a vRefNum/parID pair to use with the HXxx calls?
-
- A: Use GetWDInfo, which is declared as:
-
- Pascal OSErr GetWDInfo ( short wdRefNum , short * vRefNum , long * parID
- , OSType * procID ) ;
-
- The procID parameter must be non-NULL and point to an OSType variable,
- but the value of that variable can and should be ignored.
-
- It is recommended that, as soon as you get your hands on a wdRefNum, for
- instance from SFGetFile, you directly convert it into a vRefNum/parID
- pair and always use the latter to reference the folder.
-
- 4.5) Q: How do I select a folder using SFGetFile?
-
- A: This requires a custom dialog with a filter proc. It is too
- complicated to show here, but not totally impossible to comprehend.
- There is sample code on ftp.apple.com, in the directory dts/snippets, on
- how to do this.
-
- 4.6) Q: How do I get the full path of a file referenced by a vRefNum,
- parID and name?
-
- A: You don't.
-
- OK, I cheated you. There is exactly ONE valid reason to get the full
- path of a file (or folder, for that matter) and that is to display its
- location to the user in, say, a settings dialog. To actually save the
- location of the file you should do this: (assuming the file is in an
- FSSpec called theFile - you can use FSSpecs in your program even if you
- don't run under System 7; just make your own MyFSMakeFSSpec that fills
- in the FSSpec manually if it's not implemented)
-
- *code*
- if ( ! aliasManagerAvailable ) { /* System 6 ? */
- GetVolumeName ( theFile -> vRefNum , vName ) ;
- GetVolumeModDate ( vRefNum , & date ) ;
- Save ( vName , date , parID , fileName ) ;
- } else {
- NewAlias ( NULL , theFile , & theAlias ) ;
- Save ( theAlias ) ;
- DisposeHandle ( ( Handle ) theAlias ) ;
- }
- *end*
-
- If you are really concerned about these issues (of course you are!) you
- should save BOTH of these methods when available, and load back whatever
- is there that you can handle; since users may be using your application
- in a mixed System 6/System 7 environment.
-
- To get back to the file is left as an exercise for the reader.
-
- To open a file using fopen() or the Pascal equivalent, see above about
- using and not using HSetVol.
-
- 4.7) Q: What about actually getting the full path for a file? I promise
- I will only use it to show the location of a file to the user!
-
- A: Enter PBGetCatInfo, the Vegimatic of the Mac file system. Any Mac
- hacker of knowledge has taken this system call to his heart. Note that
- this sample code isn't all there, but should point you in the right
- direction:
-
- *code*
- Boolean IsFolder(FSSpec *fs) // this function is called later
- {
- CInfoPBRec rec;
-
- rec.hFileInfo.ioNamePtr = fs -> name;
- rec.hFileInfo.ioVRefNum = fs -> vRefNum;
- rec.hFileInfo.ioDirID = fs -> parID;
-
-
- if ( !fs -> name [ 0 ] )
- {
- rec . hFileInfo . ioFDirIndex = 0 ;
- } else
- {
- rec . hFileInfo . ioFDirIndex = -1 ;
- }
-
- rec . hFileInfo . ioFVersNum = 0 ;
- PBGetCatInfoSync (&rec);
-
- return(!rec.hFileInfo.ioFlAttrib & 0x10);
- }
- *end*
-
- *code*
- OSErr GetFolderParent(FSSpec *fss, FSSpec *parent)
- {
- CInfoPBRec rec;
- short err;
-
- *parent = *fss;
- rec.hFileInfo.ioNamePtr = parent -> name ;
- rec.hFileInfo.ioVRefNum = parent -> vRefNum ;
- rec.hFileInfo.ioDirID = parent -> parID ;
-
- if ( !parent -> name [ 0 ] ) // dougw -- neg of FAQ
- {
- rec . hFileInfo . ioFDirIndex = 0 ;
- }
- else
- {
- rec . hFileInfo . ioFDirIndex = -1 ;
- }
-
- rec . hFileInfo . ioFVersNum = 0 ;
- err = PBGetCatInfoSync ( & rec ) ;
-
- if ( ! ( rec . hFileInfo . ioFlAttrib & 0x10 ) ) { /* Not a folder */
- if ( ! err ) {
- err = dirNFErr ;
- }
- } else {
- parent -> parID = rec . dirInfo . ioDrParID ;
- BlockMove(rec.dirInfo.ioNamePtr, parent->name, rec.dirInfo.ioNamePtr[0]);
- }
- return err ;
- }
- *end*
-
- *code*
- OSErr GetFullPathHandle ( FSSpec * fss , Handle * h )
- {
- Handle tempH = NULL;
- FSSpec fs = * fss ;
- FSSpec sSpec;
-
- if(*h == NULL) // allocate a handle if needed
- {
- *h = NewHandle(0);
- }
-
- while ( fs . parID > 1 )
- {
- tempH = NULL ;
- PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
- PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
- HandAndHand ( * h , tempH ) ;
- SetHandleSize ( * h , 0L ) ;
- HandAndHand ( tempH , * h ) ;
- DisposeHandle ( tempH ) ;
-
- tempH = NULL ;
- GetFolderParent ( & fs , & sSpec ) ;
- fs = sSpec ;
- }
-
- // fs should now contain info about the volume itself
- PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
- PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
- HandAndHand ( * h , tempH ) ;
- SetHandleSize ( * h , 0L ) ;
- HandAndHand ( tempH , * h ) ;
- DisposeHandle ( tempH ) ;
- tempH = NULL ;
-
- if (!IsFolder ( fss ) )
- {
- SetHandleSize ( * h , GetHandleSize ( * h ) - 1 ) ;
- }
-
- DisposeHandle(tempH);
- return 0 ;
- }
- *end*
-
- 4.8) Q: So how do I get the names of the files in a directory?
-
- A: You use PBGetCatInfo again, but this time you set ioFDirIndex to 1 or
- more (you need to know the dirID and vRefNum of the folder you're
- interested in) You then call PBGetCatInfoSync for values of ioFDirIndex
- from 1 and up, until you get an fnfErr. Any other err means you are not
- allowed to get info about THAT item, but you may be for the next. Then
- collect the names in the string you made ioNamePtr point to as you go
- along. Note that you need to fill in the ioDirID field for each
- iteration through the loop, and preferably clear the ioFVersNum as well.
-
- Note that the contents of a directory may very well change while you are
- iterating over it; this is most likely on a file server that more than
- one user uses, or under System 7 where you run Personal File Share.
-
- 4.9) Q: How do I find the name of a folder for which I only know the
- dirID and vRefNum?
-
- A: You call (surprise!) PBGetCatInfo! Make ioNamePtr point to an empty
- string (but NOT NULL) of length 63 (like, an Str63) and ioFDirIndex
- negative (-1 is a given winner) - this makes PBGetCatInfo return
- information about the vRefNum/dirID folder instead of the file/folder
- specified by vRefNum, parID and name.
-
- 4.10) Q: How do I make the Finder see a new file that I created? Or if I
- changed the type of it; how do I display a new icon for it?
-
- A: You call (surprise!) PBGetCatInfo followed by PBSetCatInfo for the
- FOLDER the file is in. Inbetween, you should set ioDrMdDat to the
- current date&time. Code:
-
- *code*
- OSErr
- TouchFolder ( short vRefNum , long parID ) {
-
- CInfoPBRec rec ;
- Str63 name ;
- short err ;
-
- rec . hFileInfo . ioNamePtr = name ;
- name [ 0 ] = 0 ;
- rec . hFileInfo . ioVRefNum = vRefNum ;
- rec . hFileInfo . ioDirID = parID ;
- rec . hFileInfo . ioFDirIndex = -1 ;
- rec . hFileInfo . ioFVersNum = 0 ;
- err = PBGetCatInfoSync ( & rec ) ;
- if ( err ) {
- return err ;
- }
- GetDateTime ( & rec . dirInfo . ioDrMdDat ) ;
- rec . hFileInfo . ioVRefNum = vRefNum ;
- rec . hFileInfo . ioDirID = parID ;
- rec . hFileInfo . ioFDirIndex = -1 ;
- rec . hFileInfo . ioFVersNum = 0 ;
- rec . hFileInfo . ioNamePtr [ 0 ] = 0 ;
- err = PBSetCatInfoSync ( & rec ) ;
- return err ;
- }
- *end*
-
- 4.11) Q: Aren't we done with PBGetCatInfo soon?
-
- A: Well, it turns out that you can also find out whether an FSSpec is a
- file or a folder by calling PBGetCatInfo and check bit 4 (0x10) of
- ioFlAttr to see whether it is a folder. You may prefer to call
- ResolveAliasFile for this instead.
- You can also check the script of the file's title using PBGetCatInfo and
- check the ioFlFndrXInfo field if you want to work with other script
- systems than the Roman system.
-
- Another common use is to find out how many items are in a folder; the
- modification date of something or the correct capitalization of its name
- (since the Mac file system is case independent BUT preserves the case
- the user uses)
-
- 4.12) Q: How do I set what folder should initially be shown in the
- SFGetFile boxes?
-
- A: You stuff the dirID you want to show into the lo-mem global
- CurDirStore, and the NEGATIVE of the vRefNum you want into the lo-mem
- global SFSaveDisk.
-
- If you are using CustomGetFile and return sfSelectionChanged from an
- "init" message handler, you must remember to clear the script code, else
- the selection will not change.
-
- 4.13) Q: How do I find the folder my application started from? How do I
- find the application file that's running?
-
- A: Under System 7, you call GetProcessInformation using the
- ProcessSerialNumber kCurrentProcess with a pointer to an existing FSSpec
- in the parameter block. This will give you your file, and, by using the
- vRefNum and parID, the folder the application is in.
-
- *code*
- OSErr CurrentProcessLocation(FSSpec *applicationSpec)
- {
- ProcessSerialNumber currentPSN;
- ProcessInfoRec info;
-
- currentPSN.highLongOfPSN = 0;
- currentPSN.lowLongOfPSN = kCurrentProcess;
- info.processInfoLength = sizeof(ProcessInfoRec);
- info.processName = NULL;
- info.processAppSpec = applicationSpec;
- return ( GetProcessInformation(¤tPSN, &info) );
- }
- *end*
-
- Beware from writing to your applications resource or data forks; the
- former breaks on CDs/write protected floppies/file servers/virus
- checkers, the latter fails on PowerPC as well as in the above cases.
-
- 4.14) Q: When can I use those nifty, easy to use FSSpec calls?
-
- A: In Systems >= 7, in System 6 with QuickTime installed, in any system
- if you use the FSpCompat functions provided by MoreFiles [see below].
-
- 4.15) Q: I hate dealing with the low-level file manager stuff; why
- didn't Apple provide a complete high-level interface using FSSpecs?
-
- A: Good question. Apple, in the guise of Jim Luther of Mac Developer
- Technical Support, has written a library called MoreFiles, which not
- only provides a high-level interface to low-level file stuff, but
- provides FSSpec glue for Systems below 7. MoreFiles is available on the
- Developer CD's (see above) and also at Appple's developer ftp site.
-
- *5* Imaging with QuickDraw
-
- 5.1) Q: Why is CopyBits so slow?
-
- A: It is not. It just requires some hand-holding to get good results.
- The main rules are: Make sure the source and destination pixMaps are of
- the same depth.
-
- Make sure the front color is black and the back color is white.
-
- Use srcCopy and don't use a masking region, unless it's rectangular.
-
- Copy to an unclipped window (the frontmost window). Make sure the
- ctSeed values of the source pixMap and dest pixMap match.
-
- Copying few and large pixMaps is faster than copying many and small
- ones. Icon-sized sprites count as small ones.
-
- Make sure your source bitmap or pixelMap has the same alignment, when
- adjusted for the source and destination rect expressed in global screen
- coordinates. The necessary alignment is 32 bits (4 bytes), although 128
- bit (16 byte) alignment is probably even better on 68040 macs and won't
- hurt on other macs.
-
- Example of global alignment:
-
- Your window is positioned at (42,100) (H,V)
-
- Your destination rectangle is (10,20)-(74,52)
-
- The alignment coefficient of the rectangle in global coordinates is
- (42+10)*bitDepth where bitDepth is one of 1,2,4,8,16 or 32.
-
- Make sure your source pixmap rect has the same coeffecient modulo your
- alignment factor (in bits) For black&white macs, this is still true,
- although bitDepth is fix at 1. Offscreen pixMaps can calculate with a
- "global posistion" of 0,0 and get correct results.
-
- 5.2) Q: Why is CopyBits still too slow?
-
- A: Because there is always some overhead involved in calling QuickDraw;
- you have the trap dispatcher, clipping checks, and checking whether the
- CopyBits call is being recorded in a PICT handle (if you called
- OpenPicture)
-
- If you can't live with this, look at 4.8 below, but PLEASE try and make
- CopyBits work, and retain the CopyBits code in your application, so
- users with special monitors (accellerator cards, PowerBook color
- screens, Radius Pivot screens) can still play your game. (non-game
- applications don't need more speed than CopyBits can give at its max.
- Promise!)
-
- 5.3) Q: What is the fastest way to set one pixel?
-
- A: On 68k Macs, NOT SetCPixel()! Assuming you have the correct ForeColor()
- set, you can set the pen size to (1,0) and call Line (0,1)
-
- I have heard PaintRect is good for this but requires slightly more code.
- Using PaintRect eliminates a trap call.
-
- 5.4) Q: Why do pictures I record suddenly draw as empty space or not
- draw at all?
-
- A: When recording pictures, you have to set the clipping area to exactly
- the frame of the picture you are recording. This is because it is
- initally set at -32768,32727 in both directions, and offsetting the
- picture even one pixel when drawing it will result in the region
- wrapping around and becoming empty.
-
- When recording pictures, do this:
-
- *code*
- PicHandle h = OpenPicture ( & theRect ) ;
- ClipRect ( & theRect ) ;
- /* draw the picture */
- ClosePicture ( ) ;
- *end*
-
- 5.5) Q: Where can I find the format of picture files and
- resources?
-
- A: The format of a picture resource version 1 is defined in a technical
- note. This format is obsolete.
-
- The format of a picture resource version 2 is defined in Old Inside Mac
- vol V, with addenda in Old Inside Mac vol VI.
-
- Some things happen with QuickTime compressed pictures; try the Inside
- Mac: QuickTime book or turn to Inside Mac: Imaging with QuickDraw which
- is the definite reference on QuickDraw.
-
- The format of a picture file is the same as that of a picture resource
- with 512 added 0 bytes in front.
-
- 5.6) Q: GWorlds?
-
- A: What about them? They're great. Look them up in IM: Imaging With
- QuickDraw. Don't forget to SetGWorld back to what it was before calling
- WaitNextEvent.
-
- 5.7) Q: How do I find the current depth of the screen?
-
- A: My question to you is: What screen? Many macs have more than one
- screen attached. You can use GetDeviceList and walk the devices to find
- the screen you're looking for (use TestDeviceAttribute to see whether
- it's a screen) or you can call GetMaxDevice() to find the deepest device
- your window intersects.
-
- Once you have the device handle, finding the depth is just a
- matter of looking at the gdPMap pixMapHandle, and dereference it
- to the pmSize field. Done.
-
- 5.8) Q: Why is it a bad idea to draw directly to screen?
-
- A: Because of several reasons:
-
- - You will be incompatible with future display hardware.
-
- - You will be incompatible with some present-day display
- hardware, such as Radius Pivots and PowerBook color screens.
-
- - You have to think about a lot of things; testing it all on
- your own machine is not possible and the chances of crashing are
- great.
-
- - You will be incompatible with future hardware where devices
- may live in some unaccessible I/O space.
-
- 5.9) Q: But I really need to do it. I can't make my animation into a
- QuickTime movie, and CopyBits is too slow, even when syncing to the
- screen retrace and with my source GWorld aligned properly.
-
- A: You have to prepare yourself, and ask these questions:
-
- - Do I want to support all screens, or just 8-bit devices?
-
- - Do I have a few weeks of free time to make it work?
-
- - Do I want to get nasty mail when I break on some hardware and
- have to rev the application - even if I may not be able to get
- ahold of the hardware that makes it break?
-
- If all you're doing is rendering an image pixel-by-pixel or
- line-by-line, maybe you can draw directly into an offscreen
- pixMap/GWorld and then CopyBits the entire GWorld to screen?
- That will be more compatible, especially if you use the
- keepLocal flag when creating the GWorld.
-
- 5.10) Q: Okay, so how do I get the base address of the screen?
-
- A: "The" screen? Which screen? There may be several. The base
- address may be on an accellerated screen card. There may be more
- than one screen covering the same desktop area.
-
- Due to unfortunate circumstances, there is a bug in
- GetPixBaseAddr() that causes it to return incorrect results for
- early versions of System 7. Instead, get the baseAddr directly
- from the gdPMap handle of the GDHandle for the screen you draw
- to. This address may need switching to 32bit mode to be valid.
-
- 5.11) Q: Quit stalling and give me code!
-
- A: Okay, but I'll let you sweat over Inside Mac to figure out
- what it does. All of it is important; believe me! To make this
- code run faster, a lot of the things it does can be done once
- before starting to draw.
-
- Make sure that you have a window that covers the area where you
- are drawing, so other windows will not be overdrawn. Also make
- sure that you do not do direct-to-screen-drawing while you are
- in the background.
-
- *code*
- /* This is presently untested code */
- /* Value is dependent on what depth the screen has */
- /* This code doesn't work on non-color-quickdraw Macs (i e the MacClassic) */
- /* "where" is in GLOBAL coordinates */
- void
- SetPixel ( Point where , unsigned long value ) {
-
- Rect r ;
- GDHandle theGD ;
- char * ptr ;
- long rowBytes ;
- short bitsPerPixel ;
- PixMapHandle pmh ;
- Boolean oldMode ;
-
- r . left = where . h ;
- r . top = where . v ;
- r . right = r . left + 1 ;
- r . bottom = r . top + 1 ;
- theGD = GetMaxDevice ( & r ) ;
- if ( theGD ) {
- where . v -= ( * theGD ) -> gdRect . left ;
- where . h -= ( * theGD ) -> gdRect . top ;
- pmh = ( * theGD ) -> gdPMap ;
- rowBytes = ( ( * pmh ) -> rowBytes ) & 0x3fff ;
- ptr = ( char * ) ( * pmh ) -> baseAddr ;
- bitsPerPixel = ( * pmh ) -> pixelSize ;
- oldMode = true32b ;
- ptr += where . v * rowBytes ;
- SwapMMUMode ( & oldMode ) ;
- switch ( bitsPerPixel ) {
- case 1 :
- if ( value & 1 ) {
- ptr [ where . h >> 3 ] |= ( 128 >> ( where . h & 7 ) ) ;
- } else {
- ptr [ where . h >> 3 ] &= ~( 128 >> ( where . h & 7 ) ) ;
- }
- break ;
- case 2 :
- ptr [ where . h >> 2 ] &= ( 192 >> 2 * ( where . h & 3 ) ) ;
- ptr [ where . h >> 2 ] |= ( value & 3 ) << 2 * ( 3 - ( where . h & 3 ) ) ;
- break ;
- case 4 :
- ptr [ where . h >> 1 ] &= ( where . h & 1 ) ? 0xf : 0xf0 ;
- ptr [ where . h >> 1 ] |= ( value & 15 ) << 4 * ( 1 - ( where . h & 1 ) ) ;
- break ;
- case 8 :
- ptr [ where . h ] = value ;
- break ;
- case 16 :
- ( ( unsigned short * ) ptr ) [ where . h ] = value ;
- break ;
- case 32 :
- ( ( unsigned long * ) ptr ) [ where . h ] = value ;
- break ;
- default :
- abort ( ) ; /* Should never get here */
- }
- SwapMMUMode ( & oldMode ) ;
- }
- }
- *end*
-
- *6* Text
-
- 6.1) Q: How do I get TextEdit to display more than 32k of text?
-
- A: You don't. Truly, it's not worth it. There's a call-for-call
- TextEdit replacement called TE32k which does > 32k text, and is
- available from any recent Info-Mac mirror. It doesn't do styled text,
- though.
-
- 6.2) Q: How do I get TextEdit to display more than 32k of __styled__
- text *and* embedded objects in the text (such as pictures)?
-
- WASTE, available at ftp://ghost.dsi.unimi.it/pub2/papers/piovanel, is a
- vast improvement over TextEdit. Version 1.0 does >32k styled text
- retains compatibility with the TextEdit style scrap (which is used to
- store styled text in files such as SimpleText's, as well as in the
- clipboard), includes source code and is freeware. Really worth the
- download. Version 1.1 adds embedded objects within the text, such as
- pictures, intelligent cut-and-paste, built-in Drag Manager support,
- built-in Undo support. 1.1 is currently in alpha, but seems to be very
- stable.
-
- "But," you nervously stutter, "WASTE is in Pascal! And it's munged so
- that it won't work as an imported library w/Metrowerks C! What now?"
-
- Dan Crevier is maintaining a C port of WASTE, and the current version
- along with other WASTE goodies is at <ftp://rhino.harvard.edu/pub/dan/>.
-
- 6.3) Q: I'm too back-asswards to use WASTE 1.1. How do I include
- pictures in text using TextEdit?
-
- A: There's no really easy way (such as a TEAddPict() call), and it will
- be a nasty kludge if you do get it working, but if you can live with
- that, here's how to do it. I do recommend that you take a look at Q
- 6.2, above.
-
- Write an algorithm to get the position of a special marker character
- [Teach/SimpleText uses option-space] or text attribute that the user
- will insert wherever he wants a picture. Pass this position to a
- function similar to the one below.
-
- *code*
- /*
- TEDrawPicture
- Draw a picture within TextEdit's text.
-
- input:
- pos - the position of the special character in the text where the user
- wants a picture.
- r - size of picture
-
- output:
- r - frame in which picture was drawn
- */
-
- void TEDrawPicture(short pos,PicHandle pic,Rect &r,TEHandle theTE)
- {
- Point bottomLeft; //I think TT/ST uses topleft
-
- bottomLeft = TEGetPoint(pos, theTE);
-
- r.right = bottomLeft.h + (r.right - r.left);
- r.top = bottomLeft.v - (r.bottom - r.top);
- r.left = bottomLeft.h;
- r.bottom = bottomLeft.v;
-
- DrawPicture(pic, &r);
- }
-
- *end*
-
- I'll leave selection and hiliting as an exercise for the reader (don't
- ya love it when people say that?).
-
- Thereotically, it should be possible to kludge up TextEdit to the point
- where it would treat pictures as if they were actually letters (rather big
- letters, but letters just the same). That's what the width and word break
- hooks are for, after all. However, this would be a lot of Work, and I've
- never seen it done. One is lead to believe that it's less work to create
- an improved version of TextEdit from the ground up with picture support.
- WASTE 1.1, in fact, does this rather nicely.
-
- 6.4) Q: I have all this money, and I want to get rid of it. How do I
- edit more than 32k of styled text now?
-
- A: There are at least three solutions.
-
- 1) The Galaxy application framework comes with a styled text editting
- engine which does more than 32k of text. It also happens to support
- cross-platform application development. Pricing starts at $10000.
- <galaxy@visix.com>
-
- 2) DataPak is selling a cross-platform library called "PAIGE". It is
- written to be customizable to any extent, and you can do _anything_ in
- it (want quicktime movies that play and flow with the text while
- editting? Three pages of code; you can adapt their picture sample code.)
- Available for Mac, Windows & Never Trusted and Power Mac. Pricing at
- $5000 ($25000 for source code) - it might be cheaper if you talk to
- them. Customer support is reputed to be "lousy".
-
- 3) Or you could use WASTE 1.1 with it's embedded objects implementation
- (want quicktime movies that play and flow with the text while editing?
- One page of code, if that much.)
-
- 6.5) Q: How do I convert from a string to a floating point type?
-
- A: Once you've got an Str255, you want to call the routine
- StringToExtended to change the number into type extended80, which is the
- 80-bit floating point type. The nice thing about StringToExtended is
- that it even works in funky foreign language scripts like Chinese. To
- use the routine, you must pass it not only the Str255 that you want
- converted, but also the results of the StringToFormatRec routine and the
- GetIntlResourceTable routine. The documentation is generally difficult,
- so I'll describe the parameters and give you a code example below.
- Here's what you pass to StringToExtended:
-
- - source:
- Obviously the string representation of the number.
-
- - myFormatRec:
- This is simply the format that you expect the number to be. For
- example, if you wanted a positive integer with up to 3 decimal places,
- you would want the format to be "###". (The "#" symbol means a non-zero
- filled digit, whereas a "0" would mean zero filled.) If you wanted an
- floating point exponential notation with up to 2 digit integer portion,
- exactly 2 digit decimal portion, and exactly 1 digit after the "E", your
- format would be "##.00E+0". (Actually, in Canada, you folks might use a
- "," instead of a "." for the decimal point; if you do, then you would
- put the locally correct symbol in there.) In a format string, you can
- put the format for a positive value, a negative value, and 0 seperated
- by semicolons (e.g. "##.00E+0;-##.00E+0;0.00E+0").
-
- But myFormatRec is not the format string itself, but is an internal
- format that you get from calling StringToFormatRec. This is so you can
- store the format returned to you by StringToFormatRec and use it on
- different international systems. There is a nice editor for ResEdit for
- 'FMAT' resources that lets you type the format string and will call
- StringToFormatRec for you and create an 'FMAT' resource out of the
- result. Then you can load the 'FMAT' at run time and pass it to
- myFormatRec.
-
- - partsTable:
- The number parts table from the 'itl4' resource. If you are using
- System 7 or later, you call GetIntlResourceTable, asking it for the
- number parts table. You don't need to worry about HLock'ing itlHandle
- because StringToExtended doesn't move memory; just don't do anything
- between your call to GetIntlResourceTable and the StringToFormatRec
- routine. If you are using System 6, you need to perform the
- GetIntlResourceTable by hand. It's a few lines of code; left as an
- exercise to the reader.
-
- - x:
- The extended number to put the thing into.
-
- So, let's say you expect the user to enter a string containing up to 5
- digits in the integer with a thousand marker between the 3rd and fourth
- digit, exactly two digits after the decimal, put it in parenthesis if
- it's negative, and have it just be "0.00" if it's 0. (I will use "."
- for the decimal and "," for the thousand marker. Here's the C code
- (passing in the source string):
-
- *code*
- Handle itlHandle; /* The 'itl4' resource handle */
- long offset, length; /* Offset-length of parts table */
- NumFormatStringRec myFormatRec; /* Canonical format record */
- extended80 x; /* The number to put it into */
-
- GetIntlResourceTable (smCurrentScript, smNumberPartsTable,
- &itlHandle, &offset, &length);
- StringToFormatRec ("\p##,###.00;(##,###.00);0.00",
- (NumberParts *)(*itlHandle + offset),
- &myFormatRec);
- StringToExtended (source, &myFormatRec,
- (NumberParts *)(*itlHandle + offset),
- &x);
- *end*
-
- If you saved a format record in a resource using the 'FMAT' editor
- (which is really the preferred way to do it), you would change the code
- to look like this:
-
- *code*
- Handle itlHandle; /* The 'itl4' resource handle */
- long offset, length; /* Offset-length of parts table */
- NumFormatStringRec **myFormatRec; /* Canonical format resource */
- extended80 x; /* The number to put it into */
-
- myFormatRec = (NumFormatStringRec **)GetResource('FMAT', MY_FMAT);
- GetIntlResourceTable (smCurrentScript, smNumberPartsTable,
- &itlHandle, &offset, &length);
- StringToExtended (source, *myFormatRec,
- (NumberParts *)(*itlHandle + offset),
- &x);
- *end*
-
- The StringToExtended routines will return a result that will tell you if
- there are any parsing errors. Error checking is also left as an
- exercise to the reader.
-
- Of course, the reverse of the process (using ExtendedToString) works
- very much the same way, passing the same sorts of parameters.
-
- *7* Communications and Networking
-
- 7.1) Q: How do I get at the serial ports?
-
- A: You call OpenDriver for the names "\p.AOut" and "\p.AIn" to get at
- the modem port, and "\p.BOut" and "\p.BIn" for the printer port. The
- function RAMSDOpen was designed for the original Mac with 128 kB of
- memory and 64 kB of ROM, and has been extinct for several years.
-
- However, many users use their serial ports for MIDI, LocalTalk, graphic
- tablets, or what have you and have installed an additional serial port
- card to get more ports. What you SHOULD do as a good application is to
- use the Comm Toolbox Resource Manager to search for serial resources;
- this requires that the Comms Toolbox is present (true on earlier System
- 6 with an INIT, on later System 6 and System 7 always, as well as on
- A/UX) and that you have initialized the comms resource manager. The
- exact code follows (adapted from Inside Mac Comms Toolbox):
-
- *code*
- #include "CommResources.h"
- OSErr
- FindPorts ( Handle * portOutNames , Handle * portInNames , Handle * names , Handle * iconHandles ) {
-
- OSErr ret = noErr ;
- short old = 0 ;
- CRMRec theCRMRec , * found ;
- CRMSerialRecord * serial ;
-
- * portOutNames = NewHandle ( 0L ) ;
- * portInNames = NewHandle ( 0L ) ;
- * names = NewHandle ( 0L ) ;
- * iconHandles = NewHandle ( 0L ) ;
- while ( ! ret ) {
- theCRMRec . crmDeviceType = crmSerialDevice ;
- theCRMRec . crmDeviceID = old ;
- found = ( CRMRec * ) CRMSearch ( ( QElementPtr ) & theCRMRec ) ;
- if ( found ) {
- serial = ( CRMSerialRecord * ) found -> crmAttributes ;
- old = found -> crmDeviceID ;
- PtrAndHand ( & serial -> outputDriverName , * portOutNames ,
- sizeof ( serial -> outputDriverName ) ) ;
- PtrAndHand ( & serial -> inputDriverName , * portInNames ,
- sizeof ( serial -> inputDriverName ) ) ;
- PtrAndHand ( & serial -> name , * names ,
- sizeof ( serial -> name ) ) ;
- PtrAndHand ( & serial -> deviceIcon , * iconHandles ,
- sizeof ( serial -> deviceIcon ) ) ;
- } else {
- break ;
- }
- }
- return err ;
- }
- *end*
-
- This will create four handles with the driver names, device names and
- driver icon handles for all of the available serial devices. Then let
- the user choose with a pop-up menu or scrolling list, and save the
- choice in your settings file.
-
- You can use OpenDriver, SetReset, SetHShake, SetSetBuf, SerGetBuf and
- the other Serial Manager functions on these drivers. To write to the
- serial port, use FSWrite for synchronous writes that wait until all is
- written, or PBWrite asynchronously for queuing up data that is supposed
- to go out but you don't want to wait for it. At least once each time
- through your event loop, you should call SerGetBuf on the in driver
- reference number you got from OpenDriver, and call FSRead for that many
- bytes - neither more nor less.
-
- If you are REALLY interested in doing the right thing, you will use the
- Communications Toolbox Connection Manager instead; this will give you
- access to modems, direct lines, and networks of various kinds using the
- same API! Great for stuff like BBSes that may be on a network as well
- etc. The Comms Toolbox also provides modularized terminal emulation
- and file transfer tools, although the Apple-suplied VT102 tool is pretty
- lame, as is the VT102 mode of the VT320 tool. And it seems as though
- it was designed by people who'd never used a Mac before... more in the
- Unix style, right down to the lack of documentation and "magicCookie."
-
- 7.2) Q: Where is a Berkley sockets library for the Mac?
-
- A: There are some problems with that. MacTCP, the Mac Toolbox
- implementation of TCP/IP, doesn't have an API that looks at all like
- Berkley sockets. For instance, there is ONE paramater-block call to do
- a combined listen()/accept()/bind() - sort of. I have heard that there
- may be a socket library available by ftp from MIT but haven't seen it
- myself.
-
- There is also a pretty good C++ TCP implementation called GUSI which is
- easily handled, and it also is callable from C using the Berkley socket
- API. Apart from TCP, it also handles "standard" Mac network protocols
- such as ADSP. The big disadvantage is that it is currently only
- implemented for MPW. The ftp site is nic.switch.ch,
- software/mac/src/mpw_c.
-
- I can also recommend the Communications Toolbox; for the price of using
- an API that is a bigger pain in the ass than configuring Windoze to use
- a new peripheral device, you get the benefit of being able to use any
- kind of connection (TCP tools are available).
-
- Instead of the Comm Toolbox, one might use Apple's much improved Open
- Transport architecture. Preliminary docs are available for ftp at
- seeding.apple.com. Apple's new networking products team seems to have
- it's head screwed on tight. A refreshing change.
-
- Novell and Wollogong offer commercial socket-like libraries.
-
- 7.3) Q: Where do I find MacTCP?
-
- A: You can buy the MacTCP developers kit from APDA. It is also
- available on E T O, and if you want saner headers than those, try ftp to
- seeding.apple.com. MacTCP (the control panel) is included with System
- 7.5 and above.
-
- 7.4) Q: I'm trying to write to the serial port. It works fine on the
- following Machines, Quadra700, IIFX, Powerbook 170, Quadra 840av, but
- freezes on the Duo 230 and 280c.
-
- A: You need to call SerHShake. Otherwise you get screwed on some
- machines without a hardware handshaking cable because the port default to
- hardware handshaking.
-
- *8* IAC
-
- 8.1) Q: What are AppleEvents?
-
- A: AppleEvents are a level-5 network protocol. If you are not familiar
- with the ISO network stack, this means it's a way of structuring sessions
- between network entities (programs) that is not dependent on the
- underlying protocol (such as PPC or TCP/IP) Despite being a network
- protocol, they can be very useful on Macs that are not on a network. In
- short, they provide applications with a comprehensive way to send
- arbitrary structured data to other applications (or themselves) which
- receive the events through their main event loop.
-
- The AppleEvent Object Model is a way of looking at applications and the
- data they contain, and also a level-6 network protocol. You _can_ send
- AppleEvent Object Model data through AppleEvents (and the standard
- AppleEvents defined in the AppleEvent Registry use it) but you don't have
- to - unless you want to talk with other applications, of course, then the
- AEOM is a lingua franca.
-
- 8.2) Q: What are the four required AppleEvents?
-
- A: There are four events your application really must implement if you
- want to sell it: the kCoreEventClass class, kAEOpenApplication,
- kAEQuitApplication, kAEOpenDocuments and kAEPrintDocuments events IDs.
- When you support these events (or any AppleEvents) you will not get
- startup info through GetAppParams() anymore, unless you run under System
- 6 of course. The kAEOpenApplication event will be sent to you when the
- user double-clicks your app and it's not started yet. When receiving it,
- you can put up a new untitled window.
-
- kAEOpenDocuments is sent when the user double-clicks your apps documents.
- Note that if the first AppleEvent you receive is a kAEOpenDocuments
- event, the user started your app by double-clicking its documents.
-
- kAEPrintDocuments is sent when the user selects your documents and
- chooses "Print" in the Finder menu. If this is the first AppleEvent you
- receive, you should print the documents and then quit the application
- again; if you received a kAEOpenApplication or kAEOpenDocuments event
- before this, you should just print the documents and close them when
- you're done.
-
- kAEQuitApplication is sent to you when the user chooses "Shutdown" or
- "Restart" from the Apple Menu. You should ask the user whether he wants
- to save any unsaved changed documents, and then quit unless the user
- presses Cancel.
-
- Interestingly enough, you can use these four AppleEvents to send even to
- non-AE-aware applications, and the system will translate these events
- into fake menu selections for you.
-
- A good way of shutting down the Finder is to send it a Quit AppleEvent.
- You should send a Quit AppleEvent to File Sharing Extension before you
- shut down the Finder, though; the FSE is found by looking for a process
- with the creator 'hhgg'.
-
- 8.3) Q: Are there any limits or tradeoffs with AppleEvents?
-
- A: As always, more power means more responsibility.
-
- AppleEvents sent to applications on other Macs require authentification
- the first time they are sent. If the remote Mac allows Guests to link to
- programs, the INIT AutoGuest 2.0 might help (or the code solution that
- comes with it and you can build into your application)
-
- In the first version of the AppleEvent manager, there was a total 64K
- limit on the size of data and overhead. This limit has been lifted with
- the version of the AppleEvent manager that comes with AppleScript.
-
- AppleEvents require a lot of memory copying and handle resizing in their
- construction; this means that large AppleEvents may be slow in
- construction, especially when compared to a pure PPC Toolbox or
- ADSP/ASDSP link. The way around this is to use Jens Alfke's AEGizmos,
- available on the Developer CD, to create AppleEvents. AEGizmos are
- being integrated into System Software, so You Will be doing the right
- thing.
-
- You should use your own application signature as event class for
- AppleEvents you make up, in order not to collide with anybody else.
- Other than that, you are free to make your own events for your own
- needs, though supporting the required events and at least a subset of
- the Core event suite will buy you a lot of functinality from within
- AppleScript. Especially important are the Get Current Selection and Set
- Current Selection events (which are really Get/Set Data on the contents
- of the current selection of the application)
-
- The signature for your application SHOULD be registered with DTS to
- avoid conflicts; this is done through e-mail to
- DEVSUPPORT@AppleLink.Apple.Com and the form you use is located on the
- developer CDs and found on ftp.apple.com.
-
- 8.4) Q: How do AppleEvents interface with AppleScript?
-
- A: AppleEvents are the meat and potatoes of AppleScript. If you support
- the AppleEvent Object Model from within your application, users can
- control you through AppleScript.
-
- The first thing you should do is get ahold of Inside Mac:
- Interapplication Communication, and a copy of the AppleEvents Registry.
- The former tells you all you ever need to know about AppleEvents, while
- the latter is paramount for implementing the right standard events. If
- everybody use the standard events, dynamic data interchange between any
- applications will become sweet reality!
-
- Then there is the 'aete' resource which lets you put names on the events
- you support, so that users can "Open Terminology" on your application
- from within the Apple Script Editor and use the proper AppleScript
- commands in their scripts. The format of an aete resource is defined in
- Inside Macintosh: Interapplication Communication.
-
- 8.5) Q: Can I compile and run scripts from within my application?
-
- A: Yes, this is very simple. There are toolbox calls for reading
- scripts, compiling scripts, and executing scripts. (OSACompile,
- OSAExecute) These are all documented in Inside Mac: Interapplication
- Communication.
-
- 8.6) Q: Is this a good way of getting a macro language almost
- for free?
-
- A: "Good" is an understatement. Just let users write scripts, load them
- into menu items and go. Total systems integration in under a week,
- including adding support for the AEOM to your application.
-
- There is source code for an application called "MenuScripter" on the
- developer CD which shows you how to do an application with all of the
- menus being AppleScript scripts.
-
- 8.7) Q: Why do I get error -903 (noPortErr) when I try to send an Apple
- Event?
-
- A: Make sure the isHighLevelEventAware flag in your application's SIZE
- resource is set. The AE Manager won't allow you to send events if you're
- not able to receive them.
-
- *9* Standalone Code & Trap Patching
-
- 9.1) Q: How do I do code resources/extensions/external functions, much
- like HyperCard XCMDs only for my 68k app/extension?
-
- A: Here is what you need to do:
-
- Define a storage location for the plug-ins. such as, for an application
- called Foo, a folder called "Foo Pouch/ PlugIns/ Modules/ Tools/ Etc",
- which your installer creates, and which you search for in the same
- folder as your application, the preferences folder, and the System
- Folder (for System 6 (no preferences)) the name of the pouch folder
- should be in a 'STR ' or 'STR#' resource for easy internationalization.
-
- Next, define a resource type to hold your plug-in exectuable code. You
- should allow any resID number, since some development systems have
- restrictions on which id numbers can be used for multi-segment code
- resources.
-
- Decide whether you will allow multiple code resources per file. For
- example, Photoshop lets you bundle an import resource, an export
- resource, and a filter into the same file, each is its own resource
- type. It uses the resource name to tell the user, so each has its own
- name.
-
- Decide on the user interface to plug-ins. Commonly, at program
- start-up, you scan the pouch and collect all the files of the correct
- types. Then you scan for appropriate code resources, then put the names
- of the resources in the menus. You can also use the file names, or run
- the code resources and ask them for the correct name.
-
- Decide on the calling convention. MPW likes to pass parameters as
- longs, and pascal development systems usually can't generate C
- interfaces, so your best bet is to have the entry point of your code
- resource be something like:
-
- extern pascal long PlugIn(long selector, CallbackPtr callback,
- long param1, long param2, long param3, long refcon);
-
- where params 1 through 3 will have specific meanings depending upon
- which function selector is asking to be performed.
-
- CallbackPtr is something like this:
- typedef struct CallbackRec{
- DrawFunc erase;
- DrawFunc paint;
- }CallbackRec, *CallbackPtr;
-
- where DrawFunc is something like:
- typedef pascal void (*DrawFunc)(Rect *);
-
- This is the place where you define services that your application will
- perform when asked to by the code resource of the plug-in.
-
- You'll need to define a bunch of selectors for what you want the plug-in
- to do.
-
- You should definately give the plug-in an Init selector, and a dispose
- selector, and have Init return an error or a refcon, which will be
- passed back to the plug-in on each call, so the plug-in can have some
- persistent storage. You should definately set the CurResFile to the
- plug-in's file while it is running, so it can easily get at any
- resources it needs.
-
- The Init selector should pass the interface version in param1 and the
- program version in param2, so that the plug-in can cope with different
- versions of your program.
-
- The actual call to the plug-in looks like:
-
- *code*
- h = GetResource('PLUG', 1);
- HLock(h);
- xh = StripAddress(h);
- ((PlugInFunc) *xh)(kInit, callbacks, kInterfaceVer1, kProgVer1, 0, 0);
- HUnlock(h);
- *end*
-
- The StripAddress is important; if your app is running in 24bit mode, the
- resource handle may contain tag bits and you don't want strange things
- to happen if the code resource switches into 32bit mode (which QuickDraw
- may do, incidentally)
-
- Exactly how you structure your calling conventions is up to you; there
- is no accepted standard (except for HyperCard XCMDs, but that is
- probably overkill for you).
-
- 9.2) Q: How do I fat-patch a trap (that is, how do I patch a trap with
- both 68k and PPC code)?
-
- A: Create a normal fat routine descriptor and pass it to
- Set{Tool, OS}TrapAddress().
-
- *10* Compatibility
-
- 10.1) Q: I see all these people call Gestalt without first
- checking whether it's implemented. Isn't that bad?
-
- A: No; Gestalt and a few other traps (the HXxx file manager
- traps, and FindFolder) are implemented using glue so they do the
- right thing even if the trap is not implemented.
-
- If you want to get rid of the glue, you can #define
- SystemSevenOrLater (and, using Think C/C++, re-pre-compile
- MacHeaders) However, then you will be responsible for checking
- for these features before you use them.
-
- 10.2) Q: What more functions are implemented in glue?
-
- A: Wake Up and Smell the Glue!
-
- How often have you wished you could use that cool new ToolBox
- call, but didn't want to make your application System 7
- dependent? Well, it might be that you *could* in fact have used
- the call. Several traps are implemented in glue, that is, much
- of their functionality is linked into your application and thus
- available even if you are running under an old System.
-
- This list applies to MPW 3.2 and should also be valid for the
- current version of Think C. If you find any inaccuracies, please
- report them to me. (neeri@iis.ee.ethz.ch)
-
- FSOpen: Tries first OpenDF, then Open.
-
- HOpenResFile: Full functionality emulated if trap not available
-
- HCreateResFile: Full functionality emulated if trap not
- available
-
- FindFolder: Under System 6, understands the following values for
- folderType and returns the System Folder for all of them:
-
- kAppleMenuFolderType
-
- kControlPanelFolderType
-
- kExtensionFolderType
-
- kPreferencesFolderType
-
- kPrintMonitorDocsFolderType
-
- kStartupFolderType
-
- kSystemFolderType
-
- kTemporaryFolderType
-
- SysEnvirons: Full functionality emulated if trap not available
-
- NewGestalt: Returns an error if not implemented
-
- ReplaceGestalt: Returns an error if not implemented
-
- Gestalt: The following selectors are always implemented:
-
- vers mach sysv proc fpu
-
- qd kbd atlk ram lram
-
- 10.3) Q: I have to support System 6, don't I?
-
- A: It would be foolish to lock yourself out of the many benefits
- the System 7 API provides for software that you start to write
- now. Some of the System 6 and older things (likely SFGetFile and
- wdRefNums among others) will be phased out of the interfaces and
- lose support; especially on future platforms.
-
- The installed base of System 7 is larger than that of System 6;
- this is not surprising because Apple has been shipping System 7
- for several years with all new machines, including the LCII,
- Classic II, Performas and Color Classic. Another argument is
- that newer computer owners (having System 7) are much more
- likely to buy new software than old computer owners who have
- systems that already do what they want them to.
-
- The added work to support both System 6 and System 7 is
- significant; if you have the time and money you may want to do
- it, but only supporting System 6 and not System 7 is doomed to
- fail in the market of today.
-
- Some may call this position subjective; I call it business sense
- based on market demographics. A rule of thumb may be that if you
- target color machines only, you can just as well demand System 7
- as well.
-
- 10.4) Q: Why does my application work on an SE with accellerator
- (or a Mac II or Quadra), but not on one without?
-
- A: Assuming you're not calling Color QuickDraw (which is not
- available on accellerated SEs), you most probably have an
- odd-aligned word access somewhere.
-
- The 68000 does not allow words or longwords to be read from odd
- addresses, while the 68020 and up relaxes this restriction (it
- still is slower than aligned-word access though)
-
- This may or may not crash depending on your compiler:
-
- *code*
- struct foo {
- char c1 ;
- char c2 ;
- char c3 ;
- char c4 ;
- char c5 ;
- } bar ;
-
- long * x = ( long * ) & bar . c2 ;
- * x = 0x12345678 ; /* X is odd if compiler doesn't pad */
-
- This WILL crash on an SE/Plus/Classic/PB100:
-
- char foo [ 10 ] ;
-
- long * x = ( long * ) & foo [ 1 ] ;
- * x = 0x12345678 ;
-
- *end*
-
- 10.5) Q: Why does my application work on a IIci and a pre-1995 PowerMac
- but not on a Quadra?
-
- A: Two reasons:
-
- 1) The Quadras 900 and 950 have special processors that handle the serial
- ports; if you write directly to the serial chips, you will crash (this
- goes for the IIfx as well)
-
- 2) The Quadras have 68040 processors, as have the Centrises. These
- processors have separate instruction and data caches (like the 68030) but
- they are larger (4K each) and unlike the 68030 which is write-through
- data cached, the 68040 is copy-back data cached. This means that changes
- you make to "your code" aren't really changed all the time, since the
- changes may still be in the data cache and not written to memory when the
- CPU reads that part of memory into its I-cache. Even worse; that part
- might already have been read into the I-cache before you change it in the
- D-cache, meaning that writing out the D-cache will still not be enough.
- You need to flush both the caches when writing self-modifying code.
-
- Self-modifying code includes code that builds its own jump tables and
- code that decrypts itself and code that "stubs" MDEFs or WDEFs to jump
- back into the application code.
-
- You flush the cache using FlushDataCache() which is implemented if
- Gestalt says you have a 68020 or better processor (or if the _HwDispatch
- trap is implemented)
-
- The current PowerMac 68k emulator doesn't have the self-modifying cache
- problem, but a future faster version will.
-
- 10.6) Q: Why does my application work on my Quadra but not on my
- accellerated SE?
-
- A: You're probably calling Color QuickDraw without first checking if it's
- available. The following machines do not have color QuickDraw in ROM nor
- RAM:
-
- Mac Plus, Mac SE, Mac Classic, Mac Luggable, PowerBook 100, Outbound
-
- 10.7) Q: I do check for color quickdraw, but crash nevertheless.
-
- A: _Gestalt lies under some versions of System 7; it says that non-color
- machines HAVE color QuickDraw when you test using the
- gestaltQuickdrawFeatures selector.
-
- Instead, check the gestaltQuickdrawVersion selector, if it returns >=
- gestalt8BitQuickdraw then you can safely use gestaltQuickdrawFeatures,
- else you only have b/w QuickDraw.
-
- *11* Optional System Software
-
- *11.1* QuickTime
-
- 11.1.1) Q: I want to write a Amiga QuickTime player and need the
- CODEC format details.
-
- A: Although the structure of QuickTime movies is well documented in
- Inside Mac: QuickTime, the inner workings of the Apple compression
- modules is a trade secret that Apple will only license to you at great
- cost. Perhaps it's time for a freeware, cross-platform QuickTime codec?
-
- *12* Third-Party Solutions
-
- *12.1* Databases
-
- 12.1.1) Q: What are some royalty-free databases available for the
- Macintosh?
-
- A: These are commercial with no run-time licenses:
-
- - Prograph CPX comes with a database that can do indexes and tables.
- <sales@prograph.com>
-
- - CXBase Pro is an engine that comes with source, does tables and indexes
- in one compound file. <tse.int@applelink.apple.com>
-
- - dtF is a relational database library. <DTF.AMERICA@applelink.apple.com>
-
- NeoAccess is an object-oriented database, where you can store objects and
- retrieve by field value; it handles inheritance as well. Comes as a
- demo on the CodeWarrior CD with an unlockable archive of the real thing.
-
- 12.1.2) Q: I need a robust Client/Server database library. What do I do?
-
- A: Get the Macintosh Client/Server Database Development Summary, by Liam
- Breck. It covers software applicable to Macintosh (and cross-platform)
- client/server database development in three categories:
-
- + Client application development tools
- + Data access layers
- + Database servers
-
- The eight page (20 Kbytes ASCII text) document includes explanations of the
- three categories and describes over 30 products. Its sources are vendors'
- product literature, industry periodicals, and discussions with users and
- vendors' tech support staff. It is purely informational and contains no
- propaganda, as the author is a neutral party.
-
- To receive a copy electronically, email a request to:
- <maccsdb@external.umass.edu>. Tell 'em the Mac Programming FAQ sent
- you!
-
- *12.2* Circumvention of Toolbox Limitations
-
- 12.2.1) Q: Help! The List Manager is driving me right UP THE WALL! I
- want to throw it out and start over. What'r my options?
-
- A: The only non-framework List Manager replacement of which I'm aware is
- StoneTable, a commerical replacement library for the List Manager which
- provides many extensions including variable size columns/rows,
- column/row titles, different style/font/size/color per cell, sorting,
- edit in cell, and much more. <http://www.teleport.com/~stack>
-
- TCL, PowerPlant, and MacApp all have their own integrated list
- management solutions.
-
- *13* Dessert
-
- 13.1) Q: Dessert?
-
- A: Honey Hill Farms Cookie Jar Frozen Yoghurt or Haagen-Dazs Raspberry &
- Cream Ice Cream.
-
- Hokey-Pokey icecream with chocolate sauce and (for those who like their
- brain food firmer) Almond and Double Chocolate CookieTime cookies!?
-
- *14* Contributors
-
- [do let me know if I've forgotten you]
-
- Denis Birnie
- Liam Breck
- Scott Bronson <urge@mcl.mcl.ucsb.edu>
- Tim Converse <converse@cs.uchicago.edu>
- Bob Hablutzel
- Julian Harris
- Bruce Hoult <Bruce@hoult.actrix.gen.nz>
- Peter Jensen <pjensen@netcom.com>
- Steve Jasik <macnosy@jasik.com>
- Jonathan Kimmitt <jrrk@camcon.co.uk>
- Matthias Neeracher <neeri@iis.ee.ethz.ch>
- David P. Oster <oster@netcom.com>
- Louis M. Pecora
- Ingemar Ragnemalm <ingemar@lysator.liu.se>
- Pete Resnick <resnick@uiuc.edu>
- Phil Shapiro <phils@bedford.symantec.com>
- eric slosser <slosser@apple.com>
- M Sooriarachchi
- Bill <stack@teleport.com>
- Chris Thomas <thunderone@delphi.com>
- Doug W. <dougw@as.arizona.edu>
- Jon Watte <h+@austin.metrowerks.com>
- Rick Zaccone <zaccone@bucknell.edu>
-